package no.agens.depth.lib;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import no.agens.depth.lib.tween.interpolators.QuintOut;

/**
 * Created by danielzeller on 03.09.14.
 */
public class CircularSplashView extends View {

  private List<CircledDrawable> circles = new ArrayList<CircledDrawable>();
  private Bitmap splash;
  private int splashColor;

  public CircularSplashView(Context context) {
    super(context);
  }

  public CircularSplashView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public CircularSplashView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

  public void setSplash(Bitmap splash) {
    this.splash = splash;
  }

  public void setSplashColor(int splashColor) {
    this.splashColor = splashColor;
  }

  @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    if (circles.size() == 0) {
      introAnimate();
    }
  }

  public void introAnimate() {
    circles.clear();
    RectF expandedSizeFloat = new RectF(0, 0, getWidth(), getHeight());
    Rect expandedSizeInt = new Rect(0, 0, getWidth(), getHeight());
    RectF biggerRect = new RectF(-1, -1, getWidth() + 1, getHeight() + 1);
    circles.add(new CircleColorExpand(expandedSizeFloat, 0, 600, splashColor));
    circles.add(new CircleColorExpand(biggerRect, 70, 600, Color.WHITE));
    circles.add(new CircleBitmapExpand(expandedSizeInt, 130, 800, splash));
    for (CircledDrawable c : circles)
      c.startAnim();
  }

  @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    for (CircledDrawable circle : circles)
      circle.draw(canvas);
  }

  interface CircledDrawable {
    public void startAnim();

    public void draw(Canvas canvas);
  }

  public class CircleBitmapExpand implements CircledDrawable {
    Rect targetSize;
    Rect drawingRect;
    long startDelay;
    long animDuration;
    Bitmap bitmap;

    public CircleBitmapExpand(Rect targetSize, long startDelay, long animDuration,
        Bitmap inBitmap) {
      this.targetSize = targetSize;
      this.startDelay = startDelay;
      this.animDuration = animDuration;
      bitmap = inBitmap;
    }

    public Bitmap GetBitmapClippedCircle(Bitmap bitmap) {

      final int width = bitmap.getWidth();
      final int height = bitmap.getHeight();
      final Bitmap outputBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

      final Path path = new Path();
      path.addCircle((float) (width / 2), (float) (height / 2),
          (float) Math.min(width, (height / 2)), Path.Direction.CCW);

      final Canvas canvas = new Canvas(outputBitmap);
      canvas.clipPath(path);
      canvas.drawBitmap(bitmap, 0, 0, null);
      bitmap.recycle();
      return outputBitmap;
    }

    public void startAnim() {
      Rect startRect = new Rect(targetSize.centerX(), targetSize.centerY(), targetSize.centerX(),
          targetSize.centerY());
      drawingRect = startRect;
      ValueAnimator rectSize = ValueAnimator.ofObject(new RectEvaluator(), startRect, targetSize);
      rectSize.setDuration(animDuration);
      rectSize.setInterpolator(new QuintOut());
      rectSize.setStartDelay(startDelay);
      rectSize.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override public void onAnimationUpdate(ValueAnimator animation) {
          drawingRect = (Rect) animation.getAnimatedValue();
          invalidate();
        }
      });
      rectSize.start();
    }

    public void draw(Canvas canvas) {
      if (drawingRect != null) canvas.drawBitmap(bitmap, null, drawingRect, null);
    }
  }

  public class CircleColorExpand implements CircledDrawable {
    RectF targetSize;
    RectF drawingRect;
    long startDelay;
    long animDuration;
    private Paint paint = new Paint(Color.BLACK);

    public CircleColorExpand(RectF targetSize, long startDelay, long animDuration, int paintColor) {
      this.targetSize = targetSize;
      this.startDelay = startDelay;
      this.animDuration = animDuration;
      paint.setColor(paintColor);
      paint.setAntiAlias(true);
      paint.setDither(true);
    }

    public void startAnim() {
      RectF startRect = new RectF(targetSize.centerX(), targetSize.centerY(), targetSize.centerX(),
          targetSize.centerY());
      ValueAnimator rectSize = ValueAnimator.ofObject(new RectFEvaluator(), startRect, targetSize);
      rectSize.setDuration(animDuration);
      rectSize.setInterpolator(new QuintOut());
      rectSize.setStartDelay(startDelay);
      rectSize.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override public void onAnimationUpdate(ValueAnimator animation) {
          drawingRect = (RectF) animation.getAnimatedValue();
          invalidate();
        }
      });
      rectSize.start();
    }

    public void draw(Canvas canvas) {
      if (drawingRect != null) canvas.drawOval(drawingRect, paint);
    }
  }
}
